#include "CRCBlocks.h"

#include "../util/Bits8Sequence.h"

using namespace miniprojeto::util;

namespace miniprojeto {
namespace Redundancy{
	
CRCBlocks::CRCBlocks() {
	blockSize = BLOCK_SIZE + 2;
	block = new unsigned char [blockSize];	
}

CRCBlocks::CRCBlocks(unsigned char nBlock[], int bSize, unsigned short reminder) {
	if (nBlock != NULL) {
		setBlock(nBlock, bSize);
	} else {
		string str = "CRCBLocks::CRCBlocks(3) -> tentativa de iniciar com bloco NULLO)";
		InitializationException except(str);
		throw except;
	}
	setReminder(0);
}

CRCBlocks::CRCBlocks(unsigned char* nBlock) {
	setBlock(nBlock, BLOCK_SIZE + 2);
	reminder = 0;
	reminder = (unsigned short) block[BLOCK_SIZE];
	reminder = (reminder << 8 & 0xFF00);
	reminder = reminder | ((unsigned short) block[BLOCK_SIZE+1]);
}

void CRCBlocks::setBlock (unsigned char block[], int bSize) {
	if (bSize < BLOCK_SIZE+2) {
		for (int i = bSize -1; i < BLOCK_SIZE + 2; i++) {
			block[i] = 0xAA;
		}
	}
	this->block = block;
	this->blockSize = bSize;
}

void CRCBlocks::setReminder(unsigned short reminder) {
	block[BLOCK_SIZE] = (unsigned char) ((reminder >> 8) & 0XFF);
	block[BLOCK_SIZE+1] = (unsigned char) (reminder & 0xFF);
	this->reminder = reminder;	
}

unsigned short CRCBlocks::getReminer() {
	return reminder;	
}

bool CRCBlocks::writeFile (ofstream& out) {
	if (out.write((char*) block, BLOCK_SIZE)) {
			out.write((char*) &reminder, sizeof(short));
			return true;
	}
	return false;
}

bool CRCBlocks::readFile (ifstream& in) {
	unsigned short rem;
	if (in.read((char*) block, BLOCK_SIZE)) {
		if (in.read((char*) &rem, sizeof(short))) {
			this->setReminder(rem);
			return true;
		}
	}
	return false;
}

void CRCBlocks::setNumber(int number) {
	this->number = number;	
}

int CRCBlocks::getNumber() {
	return number;	
}

bool CRCBlocks::operator<(CRCBlocks* b) {
	return (number < b->number);
}
bool CRCBlocks::operator>(CRCBlocks* b) {
	return (number > b->number);
}
bool CRCBlocks::operator<=(CRCBlocks* b) {
	return (number <= b->number);
}
bool CRCBlocks::operator>=(CRCBlocks* b) {
	return (number >= b->number);
}

int CRCBlocks::getBlockSize() {
	return blockSize;	
}

unsigned char* CRCBlocks::getBytes() {
	return this->block;	
}

unsigned short CRCBlocks::getReminder() {
	return this->reminder;	
}

CRCBlocks::~CRCBlocks() {
	delete block;
}

const int CRCBlocks::BLOCK_SIZE = 4096;
}
}
